package com.vineetmanohar.nitrogen;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A utility class which uses code generator to convert a file path containing
 * variables into one or more files and directories in some code generation
 * context.
 * 
 * For example, if path is: entities/${entity.name}.java then it will be
 * expanded to one path per entity. If entity was "boat" and "car", then the
 * following paths will be generated:
 * 
 * entities/Boat.java
 * 
 * entities/Car.java
 * 
 * @author vineetmanohar
 */
public class PathGenerator {
	@SuppressWarnings("unused")
	private static final Log log = LogFactory.getLog(PathGenerator.class);

	/**
	 * Apply the given code generation context to the given path to produce more
	 * paths
	 * 
	 * @param codeGenerationContext
	 * @param inputPath
	 * @return a list of lexically sorted paths that will be generated
	 */
	public static PathGenerationResult generatePath(
			CodeGenerationContext codeGenerationContext, final String inputPath) {
		final ObjectModel rootModel = codeGenerationContext.getObjectModel();

		final PathGenerationResult pathGenerationResult = new PathGenerationResult();

		CrawlListener crawlListener = new CrawlListener() {
			public void primitiveModelFound(PrimitiveModel primitiveModel) {
			}

			public void objectModelFound(ObjectModel objectModel) {
				String generatedPath = resolvePath(objectModel, inputPath);
				if (isFullyResolved(generatedPath)) {
					pathGenerationResult.add(inputPath, generatedPath,
							objectModel);
				}
			}

			public void modelFound(Model model) {
			}

			public void arrayModelFound(ArrayModel arrayModel) {
			}
		};

		ModelCrawler.crawl(rootModel, crawlListener);

		return pathGenerationResult;
	}

	public static void generatePath(
			CodeGenerationContext codeGenerationContext, final String path,
			PathCollector pathCollector) {
		PathGenerationResult pathGenerationResult = generatePath(
				codeGenerationContext, path);

		for (GeneratedPath generatedPath : pathGenerationResult
				.getGeneratedPaths()) {
			pathCollector.collect(generatedPath);
		}
	}

	protected static boolean isFullyResolved(String resolvedPath) {
		return !resolvedPath.contains("$");
	}

	/**
	 * Resolve the path using inherited context
	 * 
	 * @param objectModel
	 * @param path
	 * @return
	 */
	protected static String resolvePath(ObjectModel objectModel, String path) {
		return TextGenerator.generateCode(objectModel, path);
	}
}